Skip to content

feat(llm): add Anthropic (Claude) client helper behind [llm] extra#28

Merged
hampsterx merged 1 commit into
masterfrom
feat/llm-helper
Jun 29, 2026
Merged

feat(llm): add Anthropic (Claude) client helper behind [llm] extra#28
hampsterx merged 1 commit into
masterfrom
feat/llm-helper

Conversation

@hampsterx

@hampsterx hampsterx commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Several Lambda functions independently hand-rolled the same Anthropic client + forced-tool-use call + tool_use-block parse. This adds one tested helper, nui_shared_utils.llm, so they can share it instead of diverging. Plumbing only: prompts, tool schemas, and model ids stay in the caller.

  • build_anthropic_client(mode="api_key"|"bedrock", ...) handles both auth modes: API-key (explicit -> ANTHROPIC_API_KEY env -> AWS Secrets Manager) and Bedrock IAM.
  • call_tool(client, *, tool, prompt, model, max_tokens, system=None) makes a forced tool-use call and returns the named tool's input dict, best-effort: None on any model/parse failure, never raises.
  • call_text(client, *, prompt, model, max_tokens, system=None) returns {text, input_tokens, output_tokens}; transport errors propagate.
  • Ships behind a new optional [llm] extra (anthropic[bedrock]>=0.45.0,<1.0.0), kept out of all. Lazy-loaded like the other optional integrations, so import nui_shared_utils does not import anthropic (cold-start preserved) and the top-level exports resolve to None when the extra is not installed.

Backwards compatibility

Purely additive. New module, new optional extra, new lazy exports. No existing public API, signature, or behaviour changes. Installing without [llm] is unaffected (anthropic is not a base dependency).

Changes

  • nui_shared_utils/llm.py (new), nui_shared_utils/__init__.py (lazy exports + optional submodule)
  • tests/test_llm.py (new, 21 tests), tests/test_lazy_imports.py (cold-start regression)
  • setup.py, pyproject.toml ([llm] extra, identical in both), requirements-test.txt (test dependency)
  • README.md, docs/README.md, docs/guides/llm-integration.md (new), AGENTS.md

Test plan

  • 21 unit tests (auth-mode selection, call_tool happy path + all None paths, call_text usage extraction)
  • Cold-start regression: import nui_shared_utils does not load anthropic; missing-extra resolves lazy exports to None
  • black --check and mypy clean on llm.py; python -m build + twine check pass
  • anthropic is not a base dependency (pip install -e . does not pull it)
  • CI green across Python 3.9-3.12

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added optional Anthropic (Claude) helper support with client setup plus call_text and call_tool utilities.
    • Introduced lazy top-level exports for LLM helpers (attributes become unavailable when the LLM extra isn’t installed).
    • Added a new [llm] install extra supporting both API-key and AWS Bedrock IAM auth.
  • Documentation
    • Updated README and guides with an Anthropic (Claude) integration section and installation/usage guidance.
  • Tests
    • Added regression coverage to ensure bare imports stay lightweight.
    • Added an offline unit test suite for client/auth selection and helper call behavior.

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

A new nui_shared_utils/llm.py module adds Anthropic client helpers for API-key and Bedrock IAM auth, plus forced tool-use and text-call functions. The package lazily exports these helpers, adds an llm optional dependency, and updates docs, README, and tests.

Changes

Anthropic (Claude) LLM Helper

Layer / File(s) Summary
llm.py: client construction and message helpers
nui_shared_utils/llm.py
Implements build_anthropic_client for API-key and Bedrock modes, call_tool for best-effort forced tool-use extraction, and call_text for plain text calls with token usage output.
Lazy-export wiring
nui_shared_utils/__init__.py
Adds the new llm helpers to lazy exports, marks llm as an optional submodule, and adds type-checking imports.
Optional dependency declaration
pyproject.toml, setup.py, requirements-test.txt
Adds the llm extra and test/dev dependency entries for anthropic[bedrock] across packaging and test configuration.
Unit tests and lazy-import regression
tests/test_llm.py, tests/test_lazy_imports.py
Covers client auth selection, tool/text helper behavior, failure paths, and bare-package lazy import behavior.
Docs and AGENTS.md
docs/guides/llm-integration.md, README.md, docs/README.md, AGENTS.md
Adds the integration guide, updates README usage and installation text, updates docs navigation, and documents the new module and optional dependency in AGENTS.md.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 Hop hop, a helper wakes,
Claude meets tools with careful grace.
Text and tokens flow through the reeds,
Docs and tests now match the deeds.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: a new Anthropic client helper added behind the optional [llm] extra.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/llm-helper

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • LINEAR integration encountered authorization issues. Please disconnect and reconnect the integration in the CodeRabbit UI.

Comment @coderabbitai help to get the list of available commands.

@hampsterx

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/guides/llm-integration.md`:
- Around line 130-136: The failure list for call_tool is too narrow and
underdescribes when None is returned. Update the documentation around call_tool
to say it warns and returns None for any exception raised by
client.messages.create, along with the existing missing tool_use, non-object
input, and missing tool name cases. Use the call_tool description in
llm-integration.md to locate and broaden the wording.
- Around line 83-107: The description of `call_tool` overstates its behavior by
claiming it guarantees schema validation and retries on mismatches; update the
docs in the `call_tool` / `tool_choice` example to say it only forces the named
tool and returns `tool_use.input`. Keep the `strict: True` note for the tool
schema, but clarify that the caller must still validate or coerce the returned
result rather than relying on retry guarantees.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 19a2596c-a9f0-4e9e-8cf3-d14c43d241a1

📥 Commits

Reviewing files that changed from the base of the PR and between 7d79d1f and b038307.

📒 Files selected for processing (11)
  • AGENTS.md
  • README.md
  • docs/README.md
  • docs/guides/llm-integration.md
  • nui_shared_utils/__init__.py
  • nui_shared_utils/llm.py
  • pyproject.toml
  • requirements-test.txt
  • setup.py
  • tests/test_lazy_imports.py
  • tests/test_llm.py

Comment thread docs/guides/llm-integration.md
Comment thread docs/guides/llm-integration.md Outdated
Three Lambda repos hand-rolled the same Anthropic client + forced-tool-use
call + tool_use-block parse; this adds one tested helper (nui_shared_utils.llm)
so they share it instead of diverging. Plumbing only: prompts, tool schemas,
and model ids stay in consumers.

- build_anthropic_client handles both auth modes: API-key (explicit ->
  ANTHROPIC_API_KEY env -> Secrets Manager) and Bedrock IAM.
- call_tool makes a forced tool-use call and returns the named tool's input
  dict, best-effort (None on any model/parse failure, never raises);
  call_text returns {text, input_tokens, output_tokens}.
- Ships behind a new optional [llm] extra (anthropic[bedrock]>=0.45.0,<1.0.0),
  kept out of `all`. Lazy-loaded like the other optional integrations:
  `import nui_shared_utils` does not import anthropic (cold-start preserved),
  and the top-level exports resolve to None when the extra is not installed.
- Docs: docs/guides/llm-integration.md, README usage example, AGENTS.md.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/guides/llm-integration.md`:
- Around line 83-88: The description of `strict` in the LLM integration guide is
inconsistent with the example tool shape, which can mislead readers about where
to place it. Update the wording around the tool definition to state that
`strict` is a top-level field on the tool object, not part of `input_schema`,
and ensure the explanation matches the example shown in the guide so the
`tool_choice`/tool schema usage is described consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 57ae501f-68c9-40cc-966f-30c09adc45f9

📥 Commits

Reviewing files that changed from the base of the PR and between b038307 and 49e604c.

📒 Files selected for processing (11)
  • AGENTS.md
  • README.md
  • docs/README.md
  • docs/guides/llm-integration.md
  • nui_shared_utils/__init__.py
  • nui_shared_utils/llm.py
  • pyproject.toml
  • requirements-test.txt
  • setup.py
  • tests/test_lazy_imports.py
  • tests/test_llm.py
✅ Files skipped from review due to trivial changes (4)
  • docs/README.md
  • AGENTS.md
  • setup.py
  • README.md
🚧 Files skipped from review as they are similar to previous changes (5)
  • pyproject.toml
  • requirements-test.txt
  • tests/test_lazy_imports.py
  • nui_shared_utils/llm.py
  • nui_shared_utils/init.py

Comment thread docs/guides/llm-integration.md
@hampsterx hampsterx merged commit fed8296 into master Jun 29, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant